home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir27 / calctool.zip / DISPLAY.C < prev    next >
C/C++ Source or Header  |  1992-09-09  |  7KB  |  320 lines

  1.  
  2. /*  @(#)display.c 1.8 89/11/01
  3.  *
  4.  *  Display manipulation routines used by calctool.
  5.  *
  6.  *  Copyright (c) Rich Burridge.
  7.  *                Sun Microsystems, Australia - All rights reserved.
  8.  *
  9.  *  Basic algorithms, copyright (c) Ed Falk.
  10.  *                Sun Microsystems, Mountain View.
  11.  *
  12.  *  Permission is given to distribute these sources, as long as the
  13.  *  copyright messages are not removed, and no monies are exchanged.
  14.  *
  15.  *  No responsibility is taken for any errors or inaccuracies inherent
  16.  *  either to the comments or the code of this program, but if
  17.  *  reported to me then an attempt will be made to fix them.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <strings.h>
  22. #include <math.h>
  23. #include "calctool.h"
  24. #include "color.h"
  25. #include "extern.h"
  26.  
  27.  
  28. char_val(chr)
  29. char chr ;
  30. {
  31.        if (chr >= '0' && chr <= '9') return(chr - '0') ;
  32.   else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
  33.   else return(-1) ;
  34. }
  35.  
  36.  
  37. clear_display()
  38. {
  39.   int i ;
  40.  
  41.   pointed = 0 ;
  42.   toclear = 1 ;
  43.   STRCPY(display, "0.") ;
  44.   for (i = 0; i < accuracy; i++) STRNCAT(display, "0", 1) ;
  45.   set_item(DISPLAYITEM, display) ;
  46.   hyperbolic = inverse = 0 ;
  47.   set_item(HYPITEM, "    ") ;
  48.   set_item(INVITEM, "    ") ;
  49.   disp_val = 0.0 ;
  50. }
  51.  
  52.  
  53. double
  54. convert_display()    /* Convert input string into a double. */
  55. {
  56.   int exp, exp_sign, i, inum ;
  57.   double val ;
  58.   char *optr ;
  59.  
  60.   val = 0.0 ;
  61.   exp = 0 ;
  62.   optr = display ;
  63.   while ((inum = char_val(*optr)) >= 0)
  64.     {
  65.       val = val * basevals[(int) base] + inum ;
  66.       *optr++ ;
  67.     }
  68.       
  69.   if (*optr == '.')
  70.     for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
  71.       val += inum / powers[i][(int) base] ;
  72.  
  73.   while (*optr == ' ') optr++ ;
  74.  
  75.   if (*optr != '\0')
  76.     {
  77.       if (*optr == '-') exp_sign = -1 ;
  78.       else exp_sign = 1 ;
  79.  
  80.       while ((inum = char_val(*++optr)) >= 0)
  81.         exp = exp * basevals[(int) base] + inum ;
  82.     }
  83.   exp *= exp_sign ;
  84.  
  85.   if (key_exp)
  86.     val *= pow((double) basevals[(int) base], (double) exp) ;
  87.   return(val) ;
  88. }
  89.  
  90.  
  91. get_label(n)
  92. int n ;
  93. {
  94.   if (tstate)
  95.     switch (buttons[n].value)
  96.         {
  97.           case CCTRL('c') :
  98.           case CCTRL('d') :
  99.           case CCTRL('e') :
  100.           case CCTRL('f') :
  101.           case CCTRL('g') :
  102.           case CCTRL('n') :
  103.           case CCTRL('r') :
  104.           case CCTRL('s') :
  105.           case CCTRL('t') : SPRINTF(pstr, "^%c  ", buttons[n].value + 96) ;
  106.                             break ;
  107.           case CCTRL('h') : STRCPY(pstr, "bsp ") ;
  108.                             break ;
  109.           case '\177'     : STRCPY(pstr, "del ") ;
  110.                             break ;
  111.           default         : SPRINTF(pstr, "%c   ", buttons[n].value) ;
  112.         }
  113.   else STRCPY(pstr, buttons[n].str) ;
  114. }
  115.  
  116.  
  117. initialise()
  118. {
  119.   error = 0 ;              /* Currently no display error. */
  120.   cur_op = '?' ;           /* No arithmetic operator defined yet. */
  121.   old_cal_value = '?' ;
  122.   result = 0.0 ;           /* No previous result yet. */
  123.   last_input = 0.0 ;
  124. }
  125.  
  126.  
  127. char *
  128. make_fixed(number, cmax)    /* Convert fixed number. */
  129. double number ;             /* Value to convert. */
  130. int cmax ;                  /* Maximum characters to generate. */
  131. {
  132.   char *optr ;
  133.   double val ;
  134.   int ndig ;                   /* Total number of digits to generate. */
  135.   int ddig ;                   /* Number of digits to left of . */
  136.   int dval ;
  137.  
  138.   optr = fnum ;
  139.   val = fabs(number) ;
  140.   if (number < 0.0) *optr++ = '-' ;
  141.   val += .5 / powers[accuracy][(int) base] ;
  142.  
  143.   if (val < 1.0)
  144.     {
  145.       ddig = 0 ;
  146.       *optr++ = '0' ;
  147.       cmax-- ;
  148.     }
  149.   else
  150.     {
  151.       for (ddig = 0; val >= 1.0; ddig++)
  152.         val /= powers[1][(int) base] ;
  153.     }
  154.  
  155.   ndig = MIN(ddig + accuracy, --cmax) ;
  156.  
  157.   while (ndig-- > 0)
  158.     {
  159.       if (ddig-- == 0) *optr++ = '.' ;
  160.       val *= powers[1][(int) base] ;
  161.       dval = val ;
  162.       *optr++ = digits[dval] ;
  163.       val -= (int) val ;
  164.     }
  165.   *optr++ = '\0' ;
  166.   toclear = 1 ;
  167.   pointed = 0 ;
  168.   return(fnum) ;
  169. }
  170.  
  171.  
  172. char *
  173. make_number(number)     /* Convert display value to current base. */
  174. double number ;         /* Value to convert. */
  175. {
  176.   double val ;
  177.  
  178. /*  Try to apply sanity checks to try to detect if the number to be
  179.  *  converted is not a valid number. These are based on the isnan and
  180.  *  isinf routines, which are only available on certain machines.
  181.  */
  182.  
  183.   if (number != number || (number*0 != 0))    /* Same as isnan & isinf. */
  184.     {
  185.       STRCPY(display, "Error") ;
  186.       error = 1 ;
  187.       set_item(OPITEM, "CLR") ;
  188.       return(display) ;
  189.     }
  190.  
  191.   val = fabs(number) ;
  192.   if (dtype == SCI ||
  193.       dtype == FIX && val != 0.0 && (val > max_fix[(int) base] ||
  194.                       val < exp_p1[accuracy][(int) base]))
  195.     return(make_scientific(number)) ;
  196.   else return(make_fixed(number, MAX_DIGITS)) ;
  197. }
  198.  
  199.  
  200. char *
  201. make_scientific(number)     /* Convert scientific number. */
  202. double number ;             /* Value to convert. */
  203. {
  204.   char fixed[MAX_DIGITS+1] ;
  205.   char *optr ;
  206.   double mant ;                /* Mantissa */
  207.   double val ;
  208.   int exp = 0 ;                /* Exponent */
  209.   int i ;
  210.   int eng = 0 ;                /* Scientific not engineering value. */
  211.   double atmp ;
  212.  
  213.   optr = snum ;
  214.   val = fabs(number) ;
  215.   if (number < 0.0) *optr++ = '-' ;
  216.   mant = val ;
  217.   atmp = 1.0 / powers[10][(int) base] ;
  218.  
  219.   if (mant != 0.0)
  220.     {
  221.       while (mant >= powers[10][(int) base])
  222.         {
  223.           exp += 10 ;
  224.           mant *= atmp ;
  225.         }
  226.         
  227.       while ((!eng && mant >= powers[1][(int) base]) ||
  228.              (eng && (mant >= powers[3][(int) base] || exp % 3 != 0)))
  229.         {
  230.           exp += 1 ;
  231.           mant /= powers[1][(int) base] ;
  232.         }
  233.  
  234.       while (mant < atmp)
  235.         {
  236.           exp -= 10 ;
  237.           mant *= powers[10][(int) base] ;
  238.         }
  239.  
  240.       while (mant < 1.0 || (eng && exp % 3 != 0))
  241.         {
  242.           exp -= 1 ;
  243.           mant *= powers[1][(int) base] ;
  244.         }
  245.     }    
  246.  
  247.   STRCPY(fixed, make_fixed(mant, MAX_DIGITS-6)) ;
  248.   for (i = 0; i < strlen(fixed); i++) *optr++ = fixed[i] ;
  249.  
  250.   *optr++ = 'e' ;
  251.  
  252.   if (exp < 0)
  253.     {
  254.       exp = -exp ;
  255.       *optr++ = '-' ;
  256.     }
  257.   else *optr++ = '+' ;
  258.  
  259.   if ((*optr = digits[exp / ((int) powers[2][(int) base])]) != '0')
  260.     optr++  ;
  261.   exp %= (int) powers[2][(int) base] ;
  262.   *optr++ = digits[exp / ((int) powers[1][(int) base])] ;
  263.   exp %= (int) powers[1][(int) base] ;
  264.   *optr++ = digits[exp] ;
  265.   *optr++ = '\0' ;
  266.   toclear = 1 ;
  267.   pointed = 0 ;
  268.   return(snum) ;
  269. }
  270.  
  271.  
  272. process_item(n)
  273. int n ;
  274. {
  275.   int i,isvalid ;
  276.  
  277.   if (n < 0 || n > TITEMS) return ;
  278.  
  279.   current = buttons[n].value ;
  280.   if (current == 'X') current = 'x' ;         /* Reassign "extra" values. */
  281.   if (current == '*') current = 'x' ;
  282.   if (current == '\015') current = '=' ;
  283.   if (current == 'Q') current = 'q' ;
  284.  
  285.   if (error)
  286.     {
  287.       isvalid = 0 ;                    /* Must press a valid key first. */
  288.       for (i = 0; i < MAXVKEYS; i++)
  289.         if (current == validkeys[i]) isvalid = 1 ;
  290.       if (pending == '?') isvalid = 1 ;
  291.       if (!isvalid) return ;
  292.       error = 0 ;
  293.     }
  294.  
  295.   if (pending)
  296.     {
  297.       for (n = 0; n < TITEMS; n++)
  298.         if (pending == buttons[n].value) break ;
  299.     }
  300.   switch (buttons[n].opdisp)
  301.     {
  302.       case OP_SET   : set_item(OPITEM, buttons[n].str) ;
  303.                       break ;
  304.       case OP_CLEAR : if (error) set_item(OPITEM, "CLR") ;
  305.                             else set_item(OPITEM, "") ;
  306.     }
  307.   (*buttons[n].func)() ;
  308. }
  309.  
  310.  
  311. show_display(val)
  312. double val ;
  313. {
  314.   if (!error)
  315.     {
  316.       STRCPY(display, make_number(val)) ;
  317.       set_item(DISPLAYITEM, display) ;
  318.     }
  319. }
  320.